
#include "Thread.h"


#define BASTERD_IS_WINDOWS (BASTERD_PLATFORM == BASTERD_PLATFORM_WIN32) || (BASTERD_PLATFORM == BASTERD_PLATFORM_WIN64)

#if 0

namespace basterd
{
	// --------------------------------------------------------------------
	// Thread interface
	// --------------------------------------------------------------------
	uint32 Thread::PRIORITY_MAX = 100;
	// --------------------------------------------------------------------
	uint32 Thread::PRIORITY_MIN = 0;
	// --------------------------------------------------------------------
	uint32 Thread::PRIORITY_NORMAL = 50;
	// --------------------------------------------------------------------
	Thread::Thread(void)
		: _mutex(), _state(Thread::THREAD_IDLE),
		  _runnable(0), _priority(Thread::PRIORITY_NORMAL)
	{
	}
	// --------------------------------------------------------------------
	Thread::Thread( Runnable* runner )
		: _mutex(), _state(Thread::THREAD_IDLE),
		  _runnable(runner), _priority(Thread::PRIORITY_NORMAL)
	{

	}
	// --------------------------------------------------------------------
	Thread::~Thread(void)
	{
		// deletion
		if( (_state != Thread::THREAD_IDLE) && (_state != Thread::THREAD_STOPPED) )
		{
			stop ();
		}

		loseHandle (_thread);
		_thread = 0;
	}
	// --------------------------------------------------------------------
	void Thread::setPriority( uint32 pr )
	{
		_priority = pr;
	}
	// --------------------------------------------------------------------
	uint32 Thread::getPriority(void) const
	{
		return _priority;
	}
	// --------------------------------------------------------------------
	void Thread::start(void)
	{
		// two code pieces cannot
		// MutexLocker ml(_mutex);

		if( (_state == Thread::THREAD_READY) )
		{
			// must wait until this thread stops
			BASTERD_WARN("Thread is ready to run");
			return;
		}

		if( (_state == Thread::THREAD_RUNNING) )
		{
			// must wait until this thread stops
			BASTERD_WARN("Thread is already running");
			return;
		}


		/*if(_created)
		{
			if( WaitForSingleObject (_thread, INFINITE) == WAIT_FAILED )
			{
				// TODO: find error and log it
			}
		}*/

		// creates the thread
		_thread = CreateThread (0, 0, (LPTHREAD_START_ROUTINE) _threadRunMethod, (void*)this, CREATE_SUSPENDED, 0);
		_state = Thread::THREAD_READY;

		// if thread is null??

		// OR use the MSVCRT option
		//muint dummyThreadId;
		//thread = (HANDLE)_beginthreadex (0, 0, threadRun, (void*)this,CREATE_SUSPENDED, &dummyThreadId);

		// computes the priority
		int winPriority = THREAD_PRIORITY_NORMAL;
		if (_priority <= 20)
			winPriority = THREAD_PRIORITY_LOWEST;
		else if (_priority <= 40)
			winPriority = THREAD_PRIORITY_BELOW_NORMAL;
		else if (_priority <= 60)
			winPriority = THREAD_PRIORITY_NORMAL;
		else if (_priority <= 80)
			winPriority = THREAD_PRIORITY_ABOVE_NORMAL;
		else if (_priority <= 100)
			winPriority = THREAD_PRIORITY_HIGHEST;

		// explicitly sets the priority and resumes the thread
		SetThreadPriority( _thread, winPriority);

		// NOTE: in windows the thread gets run immediately after resume.
		bool running = ( ResumeThread(_thread) != (DWORD)-1 );
		if( running )
		{
			_state = Thread::THREAD_RUNNING;
		}
	}
	// --------------------------------------------------------------------
	void Thread::stop(void)
	{
		//MutexLocker ml(_mutex);

		BASTERD_LOGF("trying to stop thread...");

		if( (_state==Thread::THREAD_READY) || (_state==Thread::THREAD_RUNNING) )
		{
			bool stillRunning = !TerminateThread (_thread, ~0);
			_state = Thread::THREAD_STOPPED;
		}
	}
	// --------------------------------------------------------------------
	void Thread::sleep( uint32 milliseconds )
	{
		Sleep(milliseconds);

	}
	// --------------------------------------------------------------------
	void Thread::join(void)
	{
		//MutexLocker ml(_mutex);

		if (isRunning())
		{
			// TODO cannot call this method from the thread itself
			if( WaitForSingleObject (thread, INFINITE) == WAIT_FAILED )
			{
				// TODO: find error and log it
			}
		}
	// --------------------------------------------------------------------
	void Thread::yield(void)
	{
		Sleep(0);
	}
	// --------------------------------------------------------------------
	bool Thread::isRunning(void) const
	{
			return _state == Thread::THREAD_RUNNING;
	}
	// --------------------------------------------------------------------
	Thread::ThreadState Thread::getState(void) const
	{
			return _state;
	}
	// --------------------------------------------------------------------
	void Thread::run(void)
	{
		// only runs if runnable is set
		if( _runnable )
		{
			_runnable->run();
		}
	}
	// --------------------------------------------------------------------
	UINT __stdcall Thread::_threadRunMethod(void* param)
	{
		Thread* thread = (Thread*)param;
			thread->_state = Thread::THREAD_RUNNING;
			// runs the thread
			thread->run();
			thread->_state = Thread::THREAD_IDLE;
		ExitThread (0); // CRT exit

		// mscrt version
		//_endthreadex (0); // msvcrt version
		return 0;
	}
	// --------------------------------------------------------------------
}

#endif
